package com.hycc.single;

import lombok.SneakyThrows;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/*
* 懒汉式单例
* */
public class LazyMan {

    //引入红绿灯标志位
    private static boolean xxNameFlag = false;

    //构造器私有
    private LazyMan(){
        //三重检测可以避免反射和getInstance()方法破坏单例模式
        //但是不能处理反射使用constructor.newInstance()方法创建多个
        synchronized (LazyMan.class){
            if(xxNameFlag == false){
                xxNameFlag=true;
            }else{
                //if(lazyMan!=null){
                    throw new RuntimeException("不要使用反射破坏单例构造器");
                //}
            }
            /*if(lazyMan!=null){
                throw new RuntimeException("不要使用反射破坏单例构造器");
            }*/
        }
    }

    //volatile 防止指令重排序
    private volatile static LazyMan lazyMan;

    //双重检测锁模式的懒汉式 DCL懒汉式
    public static LazyMan getInstance(){
        if (lazyMan ==null) {
            synchronized(LazyMan.class){
                if(lazyMan ==null){
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }

    @SneakyThrows
    //反射破坏
    public static void main(String[] args) {
        //LazyMan instance1 = LazyMan.getInstance();
        //破坏红绿灯标志位
        Field xxNameFlag = LazyMan.class.getDeclaredField("xxNameFlag");
        xxNameFlag.setAccessible(true);
        //破坏构造器
        Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        LazyMan instance2 = declaredConstructor.newInstance();
        xxNameFlag.set(instance2,false);
        LazyMan instance3 = declaredConstructor.newInstance();

        //System.out.println(instance1);
        System.out.println(instance2);
        System.out.println(instance3);
    }
}
